package com.sanjin.controller;

import com.sanjin.annotations.SysLogOperation;
import com.sanjin.config.WxAccountConfig;
import com.sanjin.convert.WxMiniUserConvert;
import com.sanjin.dto.AuthCode2Session;
import com.sanjin.dto.WxUserInfo;
import com.sanjin.entity.WxMiniUser;
import com.sanjin.exception.MyException;
import com.sanjin.form.WxLoginForm;
import com.sanjin.service.AdminService;
import com.sanjin.service.WxMiniUserService;
import com.sanjin.utils.*;
import com.sanjin.vo.ResponseVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

/**
 * @description:
 * @author: sanjin
 * @date: 2019/5/6 12:03
 */
@Api(tags = "登陆/认证接口")
@RestController
@RequestMapping("/auth")
public class AuthenticationController {

    @Autowired
    private AdminService adminService;

    @Autowired
    private WxMiniUserService wxMiniUserService;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private WxMiniUserConvert wxMiniUserConvert;

    @ApiOperation("admin 登陆获取token")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", paramType = "query"),
    })
    @PostMapping("/login/admin")
    public ResponseVo adminLogin(@RequestParam String username,
                                 @RequestParam String password) {
        if (StringUtils.isEmpty(username)
            || StringUtils.isEmpty(password)) {
            throw new MyException("username and password muse be not null");
        }
        String token = adminService.createToken(username, password);
        return ResponseVoUtils.success(token);
    }

    @ApiOperation(value = "小程序登陆注册接口", notes = "该接口返回 token")
    @PostMapping("/wxlogin")
    public ResponseVo login(@Valid @RequestBody WxLoginForm wxLoginForm) {
        // 小程序登陆
        // auth.code2Session 地址
        String url = String.format(
                " https://api.weixin.qq.com/sns/jscode2session?" +
                        "appid=%s&" + // appid
                        "secret=%s&" + // secret
                        "js_code=%s&" + // code
                        "grant_type=authorization_code",
                WxAccountConfig.APPID, WxAccountConfig.SECRET, wxLoginForm.getCode()
        );

        String jsonData = OkHttpUtils.doGet(url);
        AuthCode2Session authCode2Session = JsonUtils.jsonToPojo(jsonData, AuthCode2Session.class);
        // 验证 auth.code2Session 请求是否发送成功，0 表示成功，详见小程序官方文档
        if (authCode2Session == null || authCode2Session.getErrcode() != 0) {
            return ResponseVoUtils.error("服务端请求 auth.code2Session 接口错误");
        }
        // 根据  openid 判断该用户是否存在
        WxMiniUser queryUser = wxMiniUserService.queryWxMiniUserByOpenid(authCode2Session.getOpenid());

        String jwtToken = "";

        if (queryUser != null) {
            // 用户存在，通过 id，openid 生成 jwtToken
            jwtToken = jwtUtils.generateToken(queryUser);
        } else {
            // 进行微信开放信息的 signature 验证
            String plaintext = wxLoginForm.getRawData() + authCode2Session.getSession_key();
            // sha1 加密
            String ciphertext = EncryptUtils.sha1(plaintext);
            if (!ciphertext.equals(wxLoginForm.getSignature())) {
                return ResponseVoUtils.error("signature 不正确，用户微信开放信息错误");
            }
            // 用户不存在，进行保存
            // 从表单获取用户数据 nickname,gender,language,city,province,country,avatarUrl,
            WxUserInfo wxUserInfo = JsonUtils.jsonToPojo(wxLoginForm.getRawData(), WxUserInfo.class);
            if (wxUserInfo == null) {
                return ResponseVoUtils.error("rawData 错误,用户信息不能为空");
            }
            WxMiniUser wxMiniUser = wxMiniUserService.createWxMiniUser(wxMiniUserConvert.wxUserInfo2WxMiniUser(wxUserInfo, authCode2Session));

            // 通过 id，openid 生成 jwtToken
            jwtToken = jwtUtils.generateToken(wxMiniUser);
        }
        return ResponseVoUtils.success(jwtToken);
    }
}
